// +----------------------------------------------------------------------
// | Manong.Cloud [ 领酷码农云 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.manong.cloud All rights reserved.
// +----------------------------------------------------------------------
// | Author: 稻草人 <qinuoyun@qq.com>
// +----------------------------------------------------------------------
// | Member: 围棋 飘逸者 Loumt Silence24
// +----------------------------------------------------------------------
let DEBUG = false

let dataStorage = {};

/**
 * 打印消息
 */
function printInfo(value, message) {
  if (DEBUG) {
    console.log('【消息】' + value + ': %s', JSON.stringify(message));
  } else {

  }
}

class SocketController extends BasicController {
  /**
   * Socket用户登陆
   * @return {[type]} [description]
   */
  async actionScan(socket, data) {
    console.log("这是处理端口", data)

  }

  /**
   * Socket用户登陆
   * @return {[type]} [description]
   */
  async actionSyncTime(socket, data) {
    printInfo("执行时间同步", data)
    let timestamp = Math.round(new Date().getTime() / 1000).toString();
    return {
      "timezone": -480,
      "timestamp": Number(timestamp)
    }
  }

  /**
   * 获取签名
   * @param socket
   * @param data
   */
  async actionGetSignCode(socket, data) {
    printInfo("获取签名", data)
    let postData = {
      "device_id": data.body['device-id'],
      "signature": data.body['signature'],
      "active_code": "QN" + Math.round(new Date().getTime() / 1000).toString(),
      "secret": "SE" + Math.round(new Date().getTime() / 1000).toString(),
    }
    let returned = await db.name('drive').insert(postData);
    if (returned) {
      return {
        sign_code: data.body['signature']
      }
    }
  }

  /**
   * 执行注册
   */
  async actionRegister(socket, data) {
    printInfo("注册设备", data)
    let dataValue = await db.name('drive').where({
      "device_id": data.body['device-id'],
    }).first();
    // console.log("注册设备dataValue", dataValue.active_code)
    if (dataValue) {
      return {
        "active_code": dataValue.active_code
      }
    }
  }

  /**
   * 执行激活
   */
  async actionActive(socket, data) {
    printInfo("激活设备", data)
    let dataValue = await db.name('drive').where({
      "active_code": data.body['active_code'],
    }).first();
    if (dataValue) {
      return {
        "secret": dataValue.secret
      }
    }
  }

  /**
   * @param socket
   * @param data
   * @returns {{secret}}
   */
  async actionSubscribe(socket, data) {
    // console.log("订阅消息", data)
    printInfo("订阅消息", data)
    let dataValue = await db.name('drive').where({
      "secret": data.body['secret'],
    }).first();
    // console.log("订阅消息参数", dataValue)
    if (dataValue) {
      //此处执行同步数据格式
      let key = cache.get(dataValue.device_id);
      // console.log("订阅key", key)
      if (key) {
        // console.log("已经推送过了", key)
      } else {
        try {
          cache.set(dataValue.device_id, dataValue.device_id);
          setTimeout(async () => {
            //执行下发
            let usersArray = await this.setUserList();
            this.addUsers(socket, data, usersArray);
          }, 500)
        } catch (error) {
          console.log("查看下发错误", error)
        }
      }
      let timestamp = Math.round(new Date().getTime() / 1000).toString();
      return {
        "timezone": -480,
        "timestamp": Number(timestamp)
      }
    }
  }

  async actionPing(socket, data) {
    // console.log("心跳消息", data)
    // throw new Error("心跳失败")
  }

  actionUserRemove(socket, data) {
    console.log("处理用户删除回调", data)
    return {}
  }

  /**
   * 此处处理扫码信息
   * @param socket
   * @param data
   * @returns {Promise<void>}
   */
  async actionEventReport(socket, data) {
    if (data.body.qrcode && data.body.event === 'qrcode') {
      if (data.body.qrcode === 'demo101') {
        console.log("执行demo101", data)
        let usersArray = await this.setUserList();
        this.addUsers(socket, data, usersArray);
      } else if (data.body.qrcode === 'demo102') {
        console.log("执行demo101", data.body['device-id'])
        let device_id = data.body['device-id']
        cache.remove(device_id);
        console.log("查看", cache.get(device_id))
      } else if (data.body.qrcode === 'demo103') {
        setTimeout(() => {
          console.log("执行用户删除")
          this.delUsers(socket, data, [{userid: 'qn2022_18'}])
        }, 500)
      } else {
        console.log("扫码消息", data)
        cache.set(data.header.reqid, data.body)
        let userInfo = await this.userInfoAuth(socket, data);
        cache.set(data.header.reqid + "userInfo", userInfo)
        console.log("读取用户信息userInfo", userInfo)
        if (userInfo.certification) {
          this.openDoor(socket, data, userInfo.uid, userInfo.userType)
        } else {
          this.sweepFace(socket, data, userInfo);
        }
      }
    }
    //直接扫脸反馈-需要上报数据资料
    else if (data.body.name && data.body.uid && data.body.event === 'face') {
      console.log("扫脸成功后添加一条记录", data)
      if (data.body.name === '陌生人') {

      } else {
        cache.set(data.header.reqid, data.body)
        let id = data.body.uid.replace(/qn2022_/, "");
        this.openDoor(socket, data, id, 1)
      }
      // this.actionFdrModeExit();
    } else {
      console.log("其他扫码上报", data)
    }
    return '';
  }

  /**
   * 砸到机用户验证-用户人员认证信息
   * @return {[type]} [description]
   *     timestamp: 1657463699904,
   'device-id': '0016BG01d2q24',
   qrcode: '464a04f6f991e59b2cef8d45c07a5e66649754b111bc9ffb012ed4597d399206e79b21154606d5e1bd557ac05bf9d62d',
   event: 'qrcode'
   */
  async userInfoAuth(socket, data) {
    let return_data = {
      status: false,
      userType: '',
      IdNo: '',
      effect: '',
      expire: '',
      FaceOption: ''
    };
    let effect = '';
    let expire = '';
    let codeInfo = {
      code: data.body['device-id'],
      content: data.body['qrcode'],
      id_card: ""
    }
    // console.log("获取码的信息codeInfo", codeInfo.code)
    //通过code进行解析设备机器是否存在
    if (codeInfo.code) {
      let door = await this.modules('Building.LockDoor').where({code: codeInfo.code}).first();
      if (!door) {
        throw new Error('机器码错误');
      }
      // console.log('获取机器设备', door)
      let building_id = door.building_id;
      let time = parseInt(Date.now() / 1000);
      let user = null;
      //通过二维码内容进行处理
      if (codeInfo.content) {
        // console.log("二维码解码记录", codeInfo.content)
        let dec = decipher256(codeInfo.content);
        // console.log("dec", dec)
        let params = getParams(dec);
        // console.log("解码：读取信息", params)
        if (params.time) {
          if (parseInt(params.time) <= time) {
            throw new Error('二维码失效');
          }
        }
        if (params.uid) {
          user = await this.modules('User').where({id: params.uid}).first();
        }
      }
      // console.log("查看读取用户信息", user)
      let real_name = user.real_name;
      let UID = user.id;
      let id_card = user.id_card;
      let certification = user.certification;

      let visitor_data = null;
      if (user.company_id) {
        let company = await this.modules('Company').where({id: user.company_id}).first();

        // console.log("读取公司信息", company)
        // console.log("读取闸机楼宇", building_id)
        if (company.building_id === building_id) {
          visitor_data = {
            UID,
            id_card,
            building_id,
            company_id: user.company_id,
            type: 1
          }
          effect = new Date(new Date().toLocaleDateString()).getTime() / 1000
          expire = (new Date(new Date().toLocaleDateString()).getTime() / 1000) + 86400
        }
      }

      if (!visitor_data) {
        // console.log("进入访客测试列表")
        let invite = await this.modules('Visitor.Invite').where({UID, building_id, status: 1}).order([
          ['id', 'DESC']
        ]).first();
        // console.log("查看访客记录测试", invite)
        let time_str = date('Y-m-d H:i:s', time);
        if (invite && invite.start_time <= time_str && invite.end_time >= time_str) {
          visitor_data = {
            UID,
            id_card,
            building_id,
            company_id: invite.company_id,
            type: 2
          }
          effect = new Date(invite.start_time).getTime() / 1000
          expire = new Date(invite.end_time).getTime() / 1000
        }
      }
      // console.log("最后我可以拿到访客数据记录", visitor_data)
      if (visitor_data) {
        // let focus = await this.modules('Visitor.Focus').where({id_card}).first();
        // visitor_data['status'] = focus ? 2 : 1;
        // this.modules('Visitor').insert(visitor_data);

        return_data = {
          status: true,
          userType: visitor_data.type,
          uid: UID,
          IdNo: id_card,
          real_name: real_name,
          certification: certification,
          effect,
          expire,
          FaceOption: user.face_option ? user.face_option : 0
        };
      }
    } else {
      return false;
    }
    return return_data
  };

  /**
   * 进入扫脸
   * 读取用户信息userInfo {
  status: true,
  userType: 1,
  IdNo: '330481199305043018',
  real_name: '严天赠',
  effect: 1657382400,
  expire: 1657468800,
  FaceOption: 0
}
   */
  sweepFace(socket, data, userInfo) {
    let addface, visitor = null;
    if (userInfo.userType === 1) {
      addface = {
        "userid": "qn2022_" + userInfo.uid,
        "name": userInfo.real_name,
        "cnid": userInfo.IdNo,
        "image": "none"
      }
    }
    if (userInfo.userType === 2) {
      visitor = {
        "name": userInfo.real_name,
        "cnid": userInfo.IdNo,
      }
    }
    if (data.body.event && data.body.qrcode && userInfo) {
      let object = {
        "action": "fdr-mode-enter",
        "header": {
          "reqid": data.header.reqid
        },
        "body": {
          "timeout": 10,   // 模式超时时间，秒；如果不填默认5秒
        }
      }
      //处理用户
      if (addface) {
        object['body']['addface'] = addface;
      }
      //处理访客
      if (visitor) {
        object['body']['visitor'] = visitor;
      }
      // console.log("扫脸模式", object)
      socket.send(JSON.stringify(object))
    }
  }

  /**
   * 退出
   */
  quitFace(socket, data) {
    let object = {
      "action": "fdr-mode-exit",
      "header": {
        "reqid": data.header.reqid
      },
      "body": {}
    }
    socket.send(JSON.stringify(object))
  }

  /**
   * 执行开门
   * @param socket
   * @param data
   * @param uid
   * @param type 1=用户 2=访客
   */
  async openDoor(socket, data, uid, type = "1") {
    try {
      //获取缓存节点消息
      let dataInfo = cache.get(data.header.reqid)
      //读取用户和闸机消息
      let userData = await this.modules('User').where({id: uid}).first();
      let doorData = await this.modules('Building.LockDoor').where({code: dataInfo['device-id']}).first();

      // console.log("用户信息", userData)
      // console.log("闸机信息", doorData)

      //执行记录
      let postData = {
        UID: userData.id,
        company_id: userData.company_id || 0,
        status: 1,
        building_id: doorData.building_id,
        id_card: userData.id_card,
        type: type,
        lock_door_type: doorData.lock_door_type
      }
      //执行访问记录记录信息
      await this.modules('Visitor').insert(postData);
    } catch (e) {
      console.log("查看写入记录错误信息", e)
    }

    let object = {
      "action": "device-opendoor",
      "header": {
        "reqid": data.header.reqid
      },
      "body": {
        "userid": String(uid),
        "type": "open", // "open" - 开门动作(不填默认为开门); "close“关门动作；"silent"开门但不播放声音；"visitor"访客开门
        "delay": 12,    // 延时多久开门，不填只默认用户识别开门时间，-1为常开或常闭
      }
    }
    socket.send(JSON.stringify(object))
  }

  /**
   * 开门反馈消息结果
   * @param socket
   * @param data
   */
  actionDeviceOpendoor(socket, data) {
    console.log("开门反馈消息结果", data)
    //this.quitFace(socket, data);
  }

  /**
   * 执行用户添加
   * @param reqid
   * @param users
   */
  addUsers(socket, data, users) {
    let object = {
      "action": "user-insert",
      "header": {
        "reqid": data.header.reqid      // 透传值，设备内唯一
      },
      "body": {
        "users": users
      }
    }
    console.log("提交的数据结构", JSON.stringify(object))
    socket.send(JSON.stringify(object))
  }

  /**
   * 执行用户添加
   * @param reqid
   * @param users
   */
  delUsers(socket, data, users) {
    let object = {
      "action": "user-remove",
      "header": {
        "reqid": data.header.reqid      // 透传值，设备内唯一
      },
      "body": {
        "users": users
      }
    }
    console.log("提交的数据结构", JSON.stringify(object))
    socket.send(JSON.stringify(object))
  }


  /**
   * 执行添加用户
   * @param socket
   * @param data
   * @returns {{}}
   */
  actionUserInsert(socket, data) {
    console.log("添加用户反馈结果", data)
    return {}
  }

  /**
   * 全民认证结果
   * @param socket
   * @param data
   * @returns {{}}
   */
  actionFdrModeEnter(socket, data) {
    console.log("全民认证结果", data)
    return {}
  }

  /**
   * 扫脸模式退出结果
   * @param socket
   * @param data
   */
  actionFdrModeExit(socket, data) {
    console.log("扫脸模式退出结果", data)
    return {}
  }

  /**
   * 数据回调
   * @private
   */
  async __callback(socket, data) {
    // console.log("我是回调接口", data)
    if (data.body && data.retcode === 0) {
      if (data.body.visitor && data.body.visitor.retcode === 0) {
        let userKey = data.header.reqid + "userInfo"
        //获取缓存节点消息
        let userInfo = cache.get(userKey);
        //执行访客开门
        this.openDoor(socket, data, userInfo.uid, 2)
      }
      if (data.body.addface && data.body.addface.feature) {
        // console.log("判断这是扫脸后的回调接口", data)
        let userInfo = data.body.addface
        let id = userInfo.userid.replace(/qn2022_/, "");
        //用户读取数据库用户数据
        let userData = await this.modules('User').where({id: id}).first();
        // console.log("更新用户信息1", userData.certification)
        if (userData) {
          if (userInfo.feature && userData.certification === 0) {
            // console.log("更新用户信息2")
            await this.modules('User').where({id: id}).update({
              head: userInfo.feature,
              certification: 1
            });
          }
          //执行开门条件
          this.openDoor(socket, data, id, 1)
        }
        // console.log("我是添加人", data)
        // this.openDoor(socket, data, data.body.addface.userid)
      }
    }

    return {}
  }


  async setUserList() {
    let building_id = 8;
    let building = await this.modules("building").where({id: building_id}).select();
    let drive = await this.modules("building.LockDoor").where({building_id: building_id}).select();
    //读取该楼宇已经认证的用户
    let sql = `SELECT
	hz_company.building_id, 
	hz_user.id, 
	hz_user.real_name, 
	hz_user.id_card, 
	hz_user.company_id, 
	hz_user.head, 
	hz_user.certification
FROM
	hz_company
	INNER JOIN
	hz_user
	ON 
		hz_company.id = hz_user.company_id
WHERE
	hz_company.building_id = :building_id AND
	hz_user.certification = 1`;
    let data = await db.sql(sql, {building_id: building_id});

    let userArray = [];
    data.forEach(item => {
      let dataInfo = this.setUserInfo(item.id, item.real_name, item.id_card, item.head);
      userArray.push(dataInfo);
    })
    return userArray
  }

  /**
   * 设置用户信息
   * @param id
   * @param name
   * @param idno
   * @returns {{cards: *[], elevator: string, effect: number, expire: number, name, rules: *[], state: number, userid: string, idno: string, desc: string}}
   */
  setUserInfo(id, name, idno, head) {
    let timestamp = Math.round(new Date().getTime() / 1000).toString();
    return {
      "userid": "qn2022_" + id,     // 用户ID，全局唯一
      "name": name,     // 必填：用户姓名，防疫产品白名单功能时必须与idno匹配
      "desc": "成员",   // 可选：用户部门/住宅门牌号等，可不填写，平台可以发用户最近的组织名
      "idno": String(idno), //可选：个人身份证，在防疫产品中，白名单功能会用此实现健康码查询
      "effect": Number(timestamp),       // 用户生效时间，不填则默认为0，部分情况设备掉电丢失时间，此值填写有核验失败风险
      "expire": -1,       // 用户过期时间，不填则当前时刻+1年，建议填写一个较大值如果不用的话，-1为不限制过期
      "state": 1,                 // 用户状态，正常用户是正值，负值为黑名单，定制产品使用，可不填写
      "cards": [],
      "rules": [],
      "elevator": "0000000001000000",
      "face": {
        "feature": head
      }
    }
  }

}

export default SocketController;
